package com.llh.demo4minio.minio

import io.minio.MinioClient
import io.minio.PutObjectOptions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.core.io.ClassPathResource
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption

/**
 * minio sdk的基本用法。
 * 其官网文档sdk版本停留在3.x，sdk已经更新到7+
 * 有些API已经过时需要自己摸索。
 * <p>CreatedAt: 2020/9/15 13:58</p>
 * @author llh
 */
@SpringBootTest
class MinioTest {
    private lateinit var mc: MinioClient

    @BeforeEach
    fun init() {
        val endpoint = "http://127.0.0.1:9000"
        val accessKeyID = "minioadmin"
        val secretAccessKey = "minioadmin"
        val useSSL = false
        mc = MinioClient(endpoint, accessKeyID, secretAccessKey, useSSL)
    }

    @Test
    fun testCreateBucket() {
        val bucketName = "test-bucket"
        val has = mc.bucketExists(bucketName)
        if (has) {
            println("$bucketName 已经存在！")
        } else {
            mc.makeBucket(bucketName)
            println("$bucketName 不存在,已创建！")
        }
    }

    /**
     * minio 使用的是aws权限-资源模型，规则很复杂，
     * 参考https://docs.aws.amazon.com/AmazonS3/latest/dev/access-policy-language-overview.html
     * 此方法将生成的权限是：可以匿名访问指定存储桶内的所有内容。
     * 使用JSON字符串设定的访问策略在web管理端似乎看到不效果
     */
    @Test
    fun testAddPolicy() {
        val bucketName = "test-bucket"

        val p = """
      {
          "Statement": [
              {
                  "Action": [
                      "s3:GetBucketLocation",
                      "s3:ListBucket"
                  ],
                  "Effect": "Allow",
                  "Principal": "*",
                  "Resource": "arn:aws:s3:::$bucketName"
              },
              {
                  "Action": "s3:GetObject",
                  "Effect": "Allow",
                  "Principal": "*",
                  "Resource": "arn:aws:s3:::$bucketName/*"
              }
          ],
          "Version": "2012-10-17"
      }
""".trimIndent() // Version 是不能随便改的。
        println(p)
        mc.setBucketPolicy(bucketName, p)
        val policy = mc.getBucketPolicy(bucketName)
        println(policy)
    }

    /**
     * 测试上传文件
     * 重复上传会覆盖同名文件。
     */
    @Test
    fun testUploadFile() {
        val bucketName = "test-bucket"
        val domeFile = domeFile()

        val fis = FileInputStream(domeFile)
        val options = PutObjectOptions(
                domeFile.length(), // or -1 , auto handle file size
                PutObjectOptions.MIN_MULTIPART_SIZE.toLong())
        mc.putObject(bucketName, "demo.txt", fis, options)
    }

    private fun domeFile(filename: String = "demo.txt", context: String = "hello minio"): File {
        val path = Paths.get(ClassPathResource(filename).path)
        return if (path.toFile().exists()) {
            path.toFile()
        } else {
            Files.createFile(path)
            path.toFile().writeText(context)
            path.toFile()
        }
    }

    /**
     * 测试下载文件。
     */
    @Test
    fun testGetFile() {
        val bucketName = "test-bucket"
        val fis = mc.getObject(bucketName, "demo.txt")
        val fos = Paths.get(ClassPathResource("down.txt").path)
        Files.copy(fis, fos, StandardCopyOption.REPLACE_EXISTING)
    }


}